package com.version1.diabeco.data.actividadfisica;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.version1.diabeco.data.AbstractDao;
import com.version1.diabeco.data.DiabecoContract;
import com.version1.diabeco.model.actividadfisica.ActividadFisica;
import com.version1.diabeco.model.comida.Comida;

public final class ActividadFisicaDaoImpl extends AbstractDao implements ActividadFisicaDao {

	private Context context;

	private static ActividadFisicaDaoImpl instance;

	protected ActividadFisicaDaoImpl(Context context) {
		super(context);
	}

	/**
	 * Retrieves the singleton instance. Receives a context which is used for database initialization but also stored
	 * for subsequent sql operation calls.
	 * 
	 * This method is thread-safe.
	 * 
	 * @return ActividadFisicaDao with the instance.
	 */
	public static synchronized ActividadFisicaDaoImpl getInstance(Context context) {
		if (instance == null) {
			instance = new ActividadFisicaDaoImpl(context);
		}

		instance.setContext(context);

		return instance;
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}

	@Override
	public Long count() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ActividadFisica selectById(Long id) {

		ActividadFisica result = null;

		SQLiteDatabase db = ActividadFisicaDaoImpl.getInstance(this.getContext()).getReadableDatabase();

		// Define a projection that specifies which columns from the database
		// you will actually use after this query.
		String[] projection = { DiabecoContract.RegistroActividadFisica._ID,
				DiabecoContract.RegistroActividadFisica.COLUMNA_ALIAS,
				DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA,
				DiabecoContract.RegistroActividadFisica.COLUMNA_DESC_EJERCICIO,
				DiabecoContract.RegistroActividadFisica.COLUMNA_INTENSIDAD,
				DiabecoContract.RegistroActividadFisica.COLUMNA_DURACION };

		String selection = DiabecoContract.RegistroActividadFisica._ID + " = ?";
		String[] selectionArgs = { id.toString() };

		// How you want the results sorted in the resulting Cursor
		String sortOrder = DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA + " DESC";

		Cursor cursor = db.query(DiabecoContract.RegistroActividadFisica.TABLE_NAME, // The table to query
				projection, // The columns to return
				selection, // The columns for the WHERE clause
				selectionArgs, // The values for the WHERE clause
				null, // don't group the rows
				null, // don't filter by row groups
				sortOrder // The sort order
				);

		cursor.moveToFirst();
		result = this.retrievePhysicalExerciseMeasureFromCursor(cursor);

		db.close();
		return result;
	}

	
	@Override
	public List<ActividadFisica> selectBetweenDates(Date from, Date to) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<ActividadFisica> selectAll() {
		List<ActividadFisica> result = new ArrayList<ActividadFisica>();

		SQLiteDatabase db = ActividadFisicaDaoImpl.getInstance(this.getContext()).getReadableDatabase();

		// Define a projection that specifies which columns from the database
		// you will actually use after this query.
		String[] projection = { DiabecoContract.RegistroActividadFisica._ID,
				DiabecoContract.RegistroActividadFisica.COLUMNA_ALIAS,				
				DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA,
				DiabecoContract.RegistroActividadFisica.COLUMNA_DESC_EJERCICIO,
				DiabecoContract.RegistroActividadFisica.COLUMNA_INTENSIDAD,
				DiabecoContract.RegistroActividadFisica.COLUMNA_DURACION };

		String selection = null;
		String[] selectionArgs = null;

		// How you want the results sorted in the resulting Cursor
		String sortOrder = DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA + " DESC";

		Cursor cursor = db.query(DiabecoContract.RegistroActividadFisica.TABLE_NAME, // The table to query
				projection, // The columns to return
				selection, // The columns for the WHERE clause
				selectionArgs, // The values for the WHERE clause
				null, // don't group the rows
				null, // don't filter by row groups
				sortOrder // The sort order
				);

		while (cursor.moveToNext()) {
			ActividadFisica actFisica = this.retrievePhysicalExerciseMeasureFromCursor(cursor);
			result.add(actFisica);
		}
		
		db.close();
		return result;
	}

	@Override
	public List<ActividadFisica> select5Dias() {

		// FIXME deberia filtrar directo en la base.
		List<ActividadFisica> lista5dias = new ArrayList<ActividadFisica>();
		List<ActividadFisica> listaCompleta = this.selectAll();
		 
		Calendar c = Calendar.getInstance();
		Date now = new Date();
		c.setTime(now);
		c.add(Calendar.DATE, -5);
		c.clear(Calendar.HOUR_OF_DAY);
		c.clear(Calendar.MINUTE);
		Long hace5diasDate = c.getTime().getTime();

		for (ActividadFisica actividadFisica : listaCompleta) {
			if (actividadFisica.getFecha() > hace5diasDate) {
				lista5dias.add(actividadFisica);
			}
		}
		
		return lista5dias;
	}

	public void save(ActividadFisica actFisica) {

		// Gets the data repository in write mode
		SQLiteDatabase db = ActividadFisicaDaoImpl.getInstance(this.getContext()).getWritableDatabase();

		// Create a new map of values, where column names are the keys
		ContentValues values = new ContentValues();
		values.put(DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA, actFisica.getAlias());
		values.put(DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA, actFisica.getFecha());
		values.put(DiabecoContract.RegistroActividadFisica.COLUMNA_DESC_EJERCICIO, actFisica.getDescEjercicio());
		values.put(DiabecoContract.RegistroActividadFisica.COLUMNA_INTENSIDAD, actFisica.getIntensidad());
		values.put(DiabecoContract.RegistroActividadFisica.COLUMNA_DURACION, actFisica.getMinutos());

		long rowId;
		if (actFisica.getId() != null) {
			rowId = db.update(DiabecoContract.RegistroActividadFisica.TABLE_NAME, values,
					DiabecoContract.RegistroActividadFisica._ID + " = ?", new String[] { actFisica.getId().toString() });
		} else {
			// Insert the new row, returning the primary key value of the new row
			rowId = db.insert(DiabecoContract.RegistroActividadFisica.TABLE_NAME, null, values);
		}

		System.out.println("Registros grabados en la base de datos: " + rowId);
		
		db.close();
	}

	
	@Override
	public void deleteById(Long id) {

		// Gets the data repository in write mode
		SQLiteDatabase db = ActividadFisicaDaoImpl.getInstance(this.getContext()).getWritableDatabase();

		String removeId = id.toString();

		int rowsDeleted = db.delete(DiabecoContract.RegistroActividadFisica.TABLE_NAME,
				DiabecoContract.RegistroActividadFisica._ID + "=?", new String[] { removeId });

		if (rowsDeleted != 1) {
			throw new RuntimeException("No se pudo eliminar el registro con id " + id);
		}
		
		db.close();
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub

	}

	private ActividadFisica retrievePhysicalExerciseMeasureFromCursor(Cursor cursor) {
		ActividadFisica actFisica = new ActividadFisica();

		Long id = cursor.getLong(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica._ID));
		String alias = cursor.getString(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica.COLUMNA_ALIAS));
		Long fecha = cursor.getLong(cursor.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica.COLUMNA_FECHA));
		String descEjercicio = cursor.getString(cursor
				.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica.COLUMNA_DESC_EJERCICIO));
		String intensidad = cursor.getString(cursor
				.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica.COLUMNA_INTENSIDAD));
		Long minutos = cursor.getLong(cursor
				.getColumnIndexOrThrow(DiabecoContract.RegistroActividadFisica.COLUMNA_DURACION));

		actFisica.setId(id);
		actFisica.setAlias(alias);
		actFisica.setFecha(fecha);
		actFisica.setDescEjercicio(descEjercicio);
		actFisica.setIntensidad(intensidad);
		actFisica.setMinutos(minutos);

		System.out.println("Actividad Fisica Leida: " + actFisica);

		return actFisica;
	}

}
